﻿#region Copyright
// Copyright (c) 2011-2012 RaisingForce Team (Alikin Sergey)
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
#endregion

using RaisingForce.Raise.Language.RStates;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;

namespace RaisingForce.Raise.Tests
{


    /// <summary>
    ///Это класс теста для RStateContextTest, в котором должны
    ///находиться все модульные тесты RStateContextTest
    ///</summary>
    [TestClass()]
    public class RStateContextTest
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Получает или устанавливает контекст теста, в котором предоставляются
        ///сведения о текущем тестовом запуске и обеспечивается его функциональность.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Дополнительные атрибуты теста
        // 
        //При написании тестов можно использовать следующие дополнительные атрибуты:
        //
        //ClassInitialize используется для выполнения кода до запуска первого теста в классе
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //ClassCleanup используется для выполнения кода после завершения работы всех тестов в классе
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //TestInitialize используется для выполнения кода перед запуском каждого теста
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //TestCleanup используется для выполнения кода после завершения каждого теста
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///Тест для Конструктор RStateContext
        ///</summary>
        [TestMethod()]
        public void RStateContextConstructorTest()
        {
            IRStateContextState state =
                new RStateContext
                {
                    CounterValue = CounterValue.Get(5),
                    PreviousChain = PreviousChain.Get("A"),
                    CurrentChain = CurrentChain.Get("D"),
                    CounterInitializedState = CounterInitializedState.True,
                    CounterState = CounterState.Initialized,
                    ObjectPosition = ObjectPosition.ForwardRight
                };
            RStateContext target = new RStateContext(state);
            Assert.AreSame(state.CounterValue, target.CounterValue);
            Assert.IsFalse(state.CounterValue.IsDefault);
            Assert.AreSame(state.PreviousChain, target.PreviousChain);
            Assert.IsFalse(state.PreviousChain.IsDefault);
            Assert.AreSame(state.CurrentChain, target.CurrentChain);
            Assert.IsFalse(state.CurrentChain.IsDefault);
            Assert.AreSame(state.CounterInitializedState, target.CounterInitializedState);
            Assert.IsFalse(state.CounterInitializedState.IsDefault);
            Assert.AreSame(state.CounterState, target.CounterState);
            Assert.IsFalse(state.CounterState.IsDefault);
            Assert.AreSame(state.ObjectPosition, target.ObjectPosition);
            Assert.IsFalse(state.ObjectPosition.IsDefault);
            // changing target, but state should not change
            target.CounterValue = CounterValue.None;
            target.PreviousChain = PreviousChain.None;
            target.CurrentChain = CurrentChain.Get("B");
            target.CounterInitializedState = CounterInitializedState.False;
            target.CounterState = CounterState.NotInitialized;
            target.ObjectPosition = ObjectPosition.None;
            Assert.AreNotSame(state.CounterValue, target.CounterValue);
            Assert.AreNotSame(state.PreviousChain, target.PreviousChain);
            Assert.AreNotSame(state.CurrentChain, target.CurrentChain);
            Assert.AreNotSame(state.CounterInitializedState, target.CounterInitializedState);
            Assert.AreNotSame(state.CounterState, target.CounterState);
            Assert.AreNotSame(state.ObjectPosition, target.ObjectPosition);
        }

        /// <summary>
        ///Тест для Конструктор RStateContext
        ///</summary>
        [TestMethod()]
        public void RStateContextConstructorTest1()
        {
            RStateContext target = new RStateContext();
            Assert.AreSame(target.CounterInitializedState, CounterInitializedState.Default);
            Assert.IsTrue(target.CounterInitializedState.IsDefault);
            Assert.AreSame(target.CounterState, CounterState.Default);
            Assert.IsTrue(target.CounterState.IsDefault);
            Assert.AreSame(target.CounterValue, CounterValue.Default);
            Assert.IsTrue(target.CounterValue.IsDefault);
            Assert.AreSame(target.CurrentChain, CurrentChain.Default);
            Assert.IsTrue(target.CurrentChain.IsDefault);
            Assert.AreSame(target.ObjectPosition, ObjectPosition.Default);
            Assert.IsTrue(target.ObjectPosition.IsDefault);
            Assert.AreSame(target.PreviousChain, PreviousChain.Default);
            Assert.IsTrue(target.PreviousChain.IsDefault);
        }

        /// <summary>
        ///Тест для Clone
        ///</summary>
        [TestMethod()]
        public void CloneTest()
        {
            RStateContext target = new RStateContext();
            target.ObjectPosition = ObjectPosition.Right;
            target.PreviousChain = (PreviousChain)CurrentChain.Get("D");
            Assert.AreSame(PreviousChain.Get("D"), target.PreviousChain);
            RStateContext expected = target;
            RStateContext actual;
            actual = target.Clone();
            Assert.AreEqual(expected, actual);
            actual.PropertyChanged += (s, e) => Assert.Fail();
            expected.PropertyChanged +=
                (s, e) =>
                {
                    Assert.AreEqual(e.PropertyName, "ObjectPosition");
                };
            expected.ObjectPosition = ObjectPosition.Backward;
            Assert.AreNotEqual(expected, actual);
            expected.ObjectPosition = ObjectPosition.Right;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для Equals
        ///</summary>
        [TestMethod()]
        public void EqualsTest()
        {
            RStateContext target = new RStateContext { CounterState = CounterState.Initialized };
            RStateContext other = new RStateContext { CounterState = CounterState.Initialized };
            bool expected = true;
            bool actual;
            actual = target.Equals(other);
            Assert.AreEqual(expected, actual);
            actual = target.Equals((IRStateContextState)other);
            Assert.AreEqual(expected, actual);
            actual = target.Equals((object)other);
            Assert.AreEqual(expected, actual);
            other.CounterState = CounterState.NotInitialized;
            expected = false;
            actual = target.Equals(other);
            Assert.AreEqual(expected, actual);
            actual = target.Equals((IRStateContextState)other);
            Assert.AreEqual(expected, actual);
            actual = target.Equals((object)other);
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для GetHashCode
        ///</summary>
        [TestMethod()]
        public void GetHashCodeTest()
        {
            RStateContext target = new RStateContext { CounterState = CounterState.Initialized };
            int expected = new RStateContext { CounterState = CounterState.Initialized }.GetHashCode();
            int actual;
            actual = target.GetHashCode();
            Assert.AreEqual(expected, actual);
            expected = new RStateContext().GetHashCode();
            actual = target.GetHashCode();
            Assert.AreNotEqual(expected, actual);
        }

        /// <summary>
        ///Тест для CounterInitializedState
        ///</summary>
        [TestMethod()]
        public void CounterInitializedStateTest()
        {
            RStateContext target = new RStateContext();
            target.PropertyChanged += (s, e) => Assert.AreEqual("CounterInitializedState", e.PropertyName);
            CounterInitializedState expected = CounterInitializedState.True;
            CounterInitializedState actual;
            target.CounterInitializedState = expected;
            actual = target.CounterInitializedState;
            Assert.AreEqual(expected, actual);
            target.CounterInitializedState = CounterInitializedState.False;
            actual = target.CounterInitializedState;
            Assert.AreNotEqual(expected, actual);
            expected = target.GetValue<CounterInitializedState>();
            Assert.AreEqual(expected, actual);
            expected = CounterInitializedState.True;
            target.SetValue(expected);
            actual = target.CounterInitializedState;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для CounterState
        ///</summary>
        [TestMethod()]
        public void CounterStateTest()
        {
            RStateContext target = new RStateContext();
            target.PropertyChanged += (s, e) => Assert.AreEqual("CounterState", e.PropertyName);
            CounterState expected = CounterState.NotInitialized;
            CounterState actual;
            target.CounterState = expected;
            actual = target.CounterState;
            Assert.AreEqual(expected, actual);
            target.CounterState = CounterState.Initialized;
            actual = target.CounterState;
            Assert.AreNotEqual(expected, actual);
            expected = target.GetValue<CounterState>();
            Assert.AreEqual(expected, actual);
            expected = CounterState.NotInitialized;
            target.SetValue(expected);
            actual = target.CounterState;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для CounterValue
        ///</summary>
        [TestMethod()]
        public void CounterValueTest()
        {
            RStateContext target = new RStateContext();
            target.PropertyChanged += (s, e) => Assert.AreEqual("CounterValue", e.PropertyName);
            CounterValue expected = CounterValue.Get(1);
            CounterValue actual;
            target.CounterValue = expected;
            actual = target.CounterValue;
            Assert.AreEqual(expected, actual);
            target.CounterValue = CounterValue.Get(2);
            actual = target.CounterValue;
            Assert.AreNotEqual(expected, actual);
            expected = target.GetValue<CounterValue>();
            Assert.AreEqual(expected, actual);
            expected = CounterValue.None;
            target.SetValue(expected);
            actual = target.CounterValue;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для CurrentChain
        ///</summary>
        [TestMethod()]
        public void CurrentChainTest()
        {
            RStateContext target = new RStateContext();
            target.PropertyChanged += (s, e) => Assert.AreEqual("CurrentChain", e.PropertyName);
            CurrentChain expected = CurrentChain.Get("B");
            CurrentChain actual;
            target.CurrentChain = expected;
            actual = target.CurrentChain;
            Assert.AreEqual(expected, actual);
            target.CurrentChain = CurrentChain.Get("A");
            actual = target.CurrentChain;
            Assert.AreNotEqual(expected, actual);
            expected = target.GetValue<CurrentChain>();
            Assert.AreEqual(expected, actual);
            expected = CurrentChain.Default;
            target.SetValue(expected);
            actual = target.CurrentChain;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для ObjectPosition
        ///</summary>
        [TestMethod()]
        public void ObjectPositionTest()
        {
            RStateContext target = new RStateContext();
            target.PropertyChanged += (s, e) => Assert.AreEqual("ObjectPosition", e.PropertyName);
            ObjectPosition expected = ObjectPosition.None;
            ObjectPosition actual;
            target.ObjectPosition = expected;
            actual = target.ObjectPosition;
            Assert.AreEqual(expected, actual);
            target.ObjectPosition = ObjectPosition.ForwardLeft;
            actual = target.ObjectPosition;
            Assert.AreNotEqual(expected, actual);
            expected = target.GetValue<ObjectPosition>();
            Assert.AreEqual(expected, actual);
            expected = ObjectPosition.Left;
            target.SetValue(expected);
            actual = target.ObjectPosition;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для PreviousChain
        ///</summary>
        [TestMethod()]
        public void PreviousChainTest()
        {
            RStateContext target = new RStateContext();
            target.PropertyChanged += (s, e) => Assert.AreEqual("PreviousChain", e.PropertyName);
            PreviousChain expected = PreviousChain.Get("C");
            PreviousChain actual;
            target.PreviousChain = expected;
            actual = target.PreviousChain;
            Assert.AreEqual(expected, actual);
            target.PreviousChain = PreviousChain.None;
            actual = target.PreviousChain;
            Assert.AreNotEqual(expected, actual);
            expected = target.GetValue<PreviousChain>();
            Assert.AreEqual(expected, actual);
            expected = PreviousChain.Get("A");
            target.SetValue(expected);
            actual = target.PreviousChain;
            Assert.AreEqual(expected, actual);
        }

        /// <summary>
        ///Тест для AsReadOnly
        ///</summary>
        [TestMethod()]
        public void AsReadOnlyTest()
        {
            RStateContext target = new RStateContext();
            IRStateContextState expected = target;
            IRStateContextState actual;
            actual = target.AsReadOnly();
            Assert.AreEqual(expected, actual);
            expected = target.AsReadOnly().AsReadOnly();
            Assert.AreEqual(expected, actual);
            expected = target.Clone().AsReadOnly();
            Assert.AreEqual(expected, actual);
            expected = target.AsReadOnly();
            Assert.AreEqual(expected, actual);
        }
    }
}
